package physics;

import build.Simulation;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;

/**
 * @author samuelrang
 *
 */
public abstract class Connector {
    private Mass myStart;
    private Mass myEnd;
    private double myLength;
    private double myK;

    /**
     * Connector between two masses. Doesn't have
     * any mass of its own so most of the behavior
     * is based on how it interacts with the two end masses.
     * @param start Mass at one end of the Spring
     * @param end Mass at the other end of the Spring
     * @param length The rest length of the spring
     * @param kVal The k Constant of the Spring
     */
    public Connector (Mass start, Mass end, double length, double kVal) {
        myStart = start;
        myEnd = end;
        myLength = length;
        myK = kVal;
    }

    /**
     * This function helps animate the movements of the Spring.
     * @param pen The Graphical tool which animates the spring
     */
    public void paint (Graphics2D pen) {
        int xStart = (int) myStart.getCenter().getX();
        int yStart = (int) myStart.getCenter().getY();
        int xEnd = (int) myEnd.getCenter().getX();
        int yEnd = (int) myEnd.getCenter().getY();
        double dx = xStart - xEnd;
        double dy = yStart - yEnd;
        double len = Math.sqrt(dx * dx + dy * dy);
        checkStyle(len, myLength, pen);
        pen.drawLine(xStart, yStart, xEnd, yEnd);
    }

    /**
     * This class determines how the particular instance gets colored based
     * on the length, and varies with what type of connector it is.
     * @param len - The color of the connector could vary based on length
     * @param restLength - Current rest length of the connector
     * @param pen - Graphics being drawn to
     */
    public abstract void checkStyle(
            double len, double restLength, Graphics2D pen);

    /**
     * This function updates the force that the spring applies
     * to its two masses, and changes the length based on the
     * position of the masses.
     * @param canvas - The board on which the animation is displayed
     * @param dt - The change in time since the last update
     */
    public void update (Simulation canvas, double dt) {
        Point2D start = myStart.getCenter();
        Point2D end = myEnd.getCenter();
        double dx = start.getX() - end.getX();
        double dy = start.getY() - end.getY();
        Force f = setForce(dx, dy);
        myStart.applyForce(f);
        f.negate();
        myEnd.applyForce(f);
    }

    /**
     * Updates the force the connector applies to its
     * two masses. This is where most of the behavior of
     * the subclasses is determined.
     * @param dx x-component of length
     * @param dy y-component of length
     * @return force - to exert on masses
     */
    public abstract Force setForce(double dx, double dy);

    /**
     * Returns the rest length of the spring.
     * @return*
     */
    public double getLength () {
        return myLength;
    }

    /**
     * Sets the rest length of the spring.
     * @param len The rest length of the Spring*
     */
    public void setLength(double len) {
        myLength = len;
    }

    /**
     * Returns the k Constant of the Spring.
     * @return*
     */
    public double getK () {
        return myK;
    }
}
